package com.kanshu.utils;

import com.kanshu.model.Novel;
import com.kanshu.model.User;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
 * @author GAIst
 * ClassName XmlReader.java
 * From
 * Description OK
 * createTime 2024年12月20日14:32:26
 */
public class XmlReader {
    /**
     * 从指定路径的 XML 文件中解析小说信息
     *
     * @param pathname XML 文件的路径
     * @return 包含小说信息的集合
     */
    public static Collection getXmlMain(String pathname) {
        Collection novelsList;
        try {
            // 创建 DocumentBuilderFactory 对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建 DocumentBuilder 对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 解析 XML 文件并获取 Document 对象
            Document document = builder.parse(new File(pathname));

            // 获取根元素
            Element root = document.getDocumentElement();
            // 获取所有 novel 元素
            NodeList novelList = root.getElementsByTagName("novel");
            novelsList = new ArrayList<>();

            // 遍历每个 novel 元素
            for (int i = 0; i < novelList.getLength(); i++) {
                Node novelNode = novelList.item(i);
                if (novelNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element novelElement = (Element) novelNode;

                    // 获取 name 元素的值
                    String name = novelElement.getElementsByTagName("name").item(0).getTextContent();
                    // 获取 author 元素的值
                    String author = novelElement.getElementsByTagName("author").item(0).getTextContent();
                    // 获取 description 元素的值
                    String description = novelElement.getElementsByTagName("description").item(0).getTextContent();
                    // 获取 filename 元素的值
                    String filename = novelElement.getElementsByTagName("filename").item(0).getTextContent();

                    // 创建 Novel 对象并添加到列表中
                    Novel novel = new Novel(description, name, author, filename);
                    novelsList.add(novel);
                }
            }
        } catch (ParserConfigurationException e) {
            // 处理 XML 解析器配置异常
            throw new RuntimeException(e);
        } catch (IOException e) {
            // 处理 IO 异常
            throw new RuntimeException(e);
        } catch (SAXException e) {
            // 处理 XML 解析异常
            throw new RuntimeException(e);
        }
        // 返回小说信息集合
        return novelsList;
    }

    /**
     * 将用户信息保存到XML文件中
     * 此方法负责将一个映射中的用户信息转换为XML格式，并将其保存到指定的文件路径中
     * 每个用户在XML中表示为一个<user>元素，其中包含<username>和<password>子元素
     *
     * @param users 包含用户信息的映射，键为用户名，值为User对象
     * @param filePath XML文件的路径
     */
    public static void saveUsersToXml(Map<String, User> users, String filePath) {
        try {
            // 创建文档工厂和文档构建器
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            // 根元素
            Document doc = docBuilder.newDocument();
            Element rootElement = doc.createElement("users");
            doc.appendChild(rootElement);

            // 遍历users集合，创建user元素
            for (Map.Entry<String, User> entry : users.entrySet()) {
                Element userElement = doc.createElement("user");

                // 创建并添加username元素
                Element usernameElement = doc.createElement("username");
                usernameElement.appendChild(doc.createTextNode(entry.getKey()));
                userElement.appendChild(usernameElement);

                // 创建并添加password元素
                Element passwordElement = doc.createElement("password");
                passwordElement.appendChild(doc.createTextNode(entry.getValue().getPassword()));
                userElement.appendChild(passwordElement);

                rootElement.appendChild(userElement);
            }

            // 写入文件
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File(filePath));

            transformer.transform(source, result);
        } catch (ParserConfigurationException | TransformerException pce) {
            pce.printStackTrace();
        }
    }

    /**
     * 从XML文件中解析用户信息
     * 该方法使用Java的JAXB库来解析XML文件，将XML文件中的用户数据转换为User对象
     *
     * @param filePath XML文件的路径
     * @return 解析得到的User对象，如果解析过程中出现错误，则返回null
     */
    public static User parseUsersXml(String filePath) {
        try {
            // 创建File对象，用于表示XML文件
            File file = new File(filePath);
            // 创建JAXBContext对象，这是JAXB工作的起点，传入User.class表示我们要解析的类是User
            JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
            // 从JAXBContext对象中创建Unmarshaller对象，用于将XML转换为Java对象
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            // 使用Unmarshaller对象解析XML文件，返回User对象
            return (User) jaxbUnmarshaller.unmarshal(file);
        } catch (JAXBException e) {
            // 如果解析过程中出现JAXB异常，打印异常信息
            e.printStackTrace();
            // 返回null表示解析失败
            return null;
        }
    }

    /**
     * 从XML文件中加载用户信息到一个用户字典中
     * 此方法负责读取指定路径的XML文件，并解析其中的用户信息，将每个用户添加到给定的用户字典中
     *
     * @param filePath XML文件的路径，用于读取用户信息
     * @param users 一个用于存储用户信息的字典，用户信息将被添加到这里
     * @return 返回更新后的用户字典，包含从XML文件中读取的用户信息
     */
    public static Map<String, User> loadUsersFromXml(String filePath, Map<String, User> users) {
        // 解析XML文件，获取用户数据对象
        User usersData = parseUsersXml(filePath);

        // 检查用户数据对象是否成功解析
        if (usersData != null) {
            // 遍历解析得到的每个用户，将其添加到用户字典中
            for (User user : usersData.getUser()) {
                users.put(user.getUsername(), user);
            }
        }

        // 返回更新后的用户字典
        return users;
    }


    /**
     * 上传小说 TODO
     * @param novelXmlPath 小说信息xml地址
     * @param novelType 小说类型
     * @param novelName 小说名称
     * @param author 小说作者
     * @param novelDescription 小说简介
     */
    public static void uploadNovel(String novelXmlPath, String novelType, String novelName, String author, String novelDescription) {
        // 从novelXmlPath地址获取信息，将novelType、novelName、author、novelDescription与老信息一起写入到novelXmlPath地址

    }
}
